package io.github.uicdb.liba.api.register.data;

import com.mojang.logging.annotations.MethodsReturnNonnullByDefault;
import net.minecraft.advancements.critereon.*;
import net.minecraft.data.BlockFamily;
import net.minecraft.data.DataGenerator;
import net.minecraft.data.recipes.*;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.ItemTags;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.item.crafting.SimpleCookingSerializer;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
@SuppressWarnings("unused")
public class VanillaRecipeProvider extends RecipeProvider {
    final List<BiConsumer<Consumer<FinishedRecipe>,VanillaRecipeProvider>> finishedRecipeConsumerList;
    public VanillaRecipeProvider(DataGenerator pGenerator, List<BiConsumer<Consumer<FinishedRecipe>,VanillaRecipeProvider>> finishedRecipeConsumerList) {
        super(pGenerator);
        this.finishedRecipeConsumerList = finishedRecipeConsumerList;
    }

    @Override
    public void buildCraftingRecipes(@Nonnull Consumer<FinishedRecipe> pFinishedRecipeConsumer) {
        finishedRecipeConsumerList.forEach(consumerConsumer -> consumerConsumer.accept(pFinishedRecipeConsumer,this));
    }
    public  InventoryChangeTrigger.TriggerInstance hasItem(ItemLike p_125978_) {
        return inventoryTrigger(ItemPredicate.Builder.item().of(p_125978_).build());
    }

    public  InventoryChangeTrigger.TriggerInstance hasItem(TagKey<Item> p_206407_) {
        return inventoryTrigger(ItemPredicate.Builder.item().of(p_206407_).build());
    }
    public static InventoryChangeTrigger.TriggerInstance has(ItemLike p_125978_) {
        return inventoryTrigger(ItemPredicate.Builder.item().of(p_125978_).build());
    }

    public static InventoryChangeTrigger.TriggerInstance has(TagKey<Item> p_206407_) {
        return inventoryTrigger(ItemPredicate.Builder.item().of(p_206407_).build());
    }
    public static void oneToOneConversionRecipe(Consumer<FinishedRecipe> p_176552_, ItemLike p_176553_, ItemLike p_176554_, @Nullable String p_176555_) {
        oneToOneConversionRecipe(p_176552_, p_176553_, p_176554_, p_176555_, 1);
    }

    public static void oneToOneConversionRecipe(Consumer<FinishedRecipe> p_176557_, ItemLike p_176558_, ItemLike p_176559_, @Nullable String p_176560_, int p_176561_) {
        ShapelessRecipeBuilder.shapeless(p_176558_, p_176561_).requires(p_176559_).group(p_176560_).unlockedBy(getHasName(p_176559_), has(p_176559_)).save(p_176557_, getConversionRecipeName(p_176558_, p_176559_));
    }

    public static void oreSmelting(Consumer<FinishedRecipe> p_176592_, List<ItemLike> p_176593_, ItemLike p_176594_, float p_176595_, int p_176596_, String p_176597_) {
        oreCooking(p_176592_, RecipeSerializer.SMELTING_RECIPE, p_176593_, p_176594_, p_176595_, p_176596_, p_176597_, "_from_smelting");
    }

    public static void oreBlasting(Consumer<FinishedRecipe> p_176626_, List<ItemLike> p_176627_, ItemLike p_176628_, float p_176629_, int p_176630_, String p_176631_) {
        oreCooking(p_176626_, RecipeSerializer.BLASTING_RECIPE, p_176627_, p_176628_, p_176629_, p_176630_, p_176631_, "_from_blasting");
    }

    public static void oreCooking(Consumer<FinishedRecipe> p_176534_, SimpleCookingSerializer<?> p_176535_, List<ItemLike> p_176536_, ItemLike p_176537_, float p_176538_, int p_176539_, String p_176540_, String p_176541_) {
        for(ItemLike itemlike : p_176536_) {
            SimpleCookingRecipeBuilder.cooking(Ingredient.of(itemlike), p_176537_, p_176538_, p_176539_, p_176535_).group(p_176540_).unlockedBy(getHasName(itemlike), has(itemlike)).save(p_176534_, getItemName(p_176537_) + p_176541_ + "_" + getItemName(itemlike));
        }

    }

    public static void netheriteSmithing(Consumer<FinishedRecipe> p_125995_, Item p_125996_, Item p_125997_) {
        UpgradeRecipeBuilder.smithing(Ingredient.of(p_125996_), Ingredient.of(Items.NETHERITE_INGOT), p_125997_).unlocks("has_netherite_ingot", has(Items.NETHERITE_INGOT)).save(p_125995_, getItemName(p_125997_) + "_smithing");
    }

    public static void planksFromLog(Consumer<FinishedRecipe> p_206409_, ItemLike p_206410_, TagKey<Item> p_206411_) {
        ShapelessRecipeBuilder.shapeless(p_206410_, 4).requires(p_206411_).group("planks").unlockedBy("has_log", has(p_206411_)).save(p_206409_);
    }

    public static void planksFromLogs(Consumer<FinishedRecipe> p_206413_, ItemLike p_206414_, TagKey<Item> p_206415_) {
        ShapelessRecipeBuilder.shapeless(p_206414_, 4).requires(p_206415_).group("planks").unlockedBy("has_logs", has(p_206415_)).save(p_206413_);
    }

    public static void woodFromLogs(Consumer<FinishedRecipe> p_126003_, ItemLike p_126004_, ItemLike p_126005_) {
        ShapedRecipeBuilder.shaped(p_126004_, 3).define('#', p_126005_).pattern("##").pattern("##").group("bark").unlockedBy("has_log", has(p_126005_)).save(p_126003_);
    }

    public static void woodenBoat(Consumer<FinishedRecipe> p_126022_, ItemLike p_126023_, ItemLike p_126024_) {
        ShapedRecipeBuilder.shaped(p_126023_).define('#', p_126024_).pattern("# #").pattern("###").group("boat").unlockedBy("in_water", insideOf(Blocks.WATER)).save(p_126022_);
    }

    public static RecipeBuilder buttonBuilder(ItemLike p_176659_, Ingredient p_176660_) {
        return ShapelessRecipeBuilder.shapeless(p_176659_).requires(p_176660_);
    }

    public static RecipeBuilder doorBuilder(ItemLike p_176671_, Ingredient p_176672_) {
        return ShapedRecipeBuilder.shaped(p_176671_, 3).define('#', p_176672_).pattern("##").pattern("##").pattern("##");
    }

    public static RecipeBuilder fenceBuilder(ItemLike p_176679_, Ingredient p_176680_) {
        int i = p_176679_ == Blocks.NETHER_BRICK_FENCE ? 6 : 3;
        Item item = p_176679_ == Blocks.NETHER_BRICK_FENCE ? Items.NETHER_BRICK : Items.STICK;
        return ShapedRecipeBuilder.shaped(p_176679_, i).define('W', p_176680_).define('#', item).pattern("W#W").pattern("W#W");
    }

    public static RecipeBuilder fenceGateBuilder(ItemLike p_176685_, Ingredient p_176686_) {
        return ShapedRecipeBuilder.shaped(p_176685_).define('#', Items.STICK).define('W', p_176686_).pattern("#W#").pattern("#W#");
    }

    public static void pressurePlate(Consumer<FinishedRecipe> p_176691_, ItemLike p_176692_, ItemLike p_176693_) {
        pressurePlateBuilder(p_176692_, Ingredient.of(p_176693_)).unlockedBy(getHasName(p_176693_), has(p_176693_)).save(p_176691_);
    }

    public static RecipeBuilder pressurePlateBuilder(ItemLike p_176695_, Ingredient p_176696_) {
        return ShapedRecipeBuilder.shaped(p_176695_).define('#', p_176696_).pattern("##");
    }

    public static void slab(Consumer<FinishedRecipe> p_176701_, ItemLike p_176702_, ItemLike p_176703_) {
        slabBuilder(p_176702_, Ingredient.of(p_176703_)).unlockedBy(getHasName(p_176703_), has(p_176703_)).save(p_176701_);
    }

    public static RecipeBuilder slabBuilder(ItemLike p_176705_, Ingredient p_176706_) {
        return ShapedRecipeBuilder.shaped(p_176705_, 6).define('#', p_176706_).pattern("###");
    }

    public static RecipeBuilder stairBuilder(ItemLike p_176711_, Ingredient p_176712_) {
        return ShapedRecipeBuilder.shaped(p_176711_, 4).define('#', p_176712_).pattern("#  ").pattern("## ").pattern("###");
    }

    public static RecipeBuilder trapdoorBuilder(ItemLike p_176721_, Ingredient p_176722_) {
        return ShapedRecipeBuilder.shaped(p_176721_, 2).define('#', p_176722_).pattern("###").pattern("###");
    }

    public static RecipeBuilder signBuilder(ItemLike p_176727_, Ingredient p_176728_) {
        return ShapedRecipeBuilder.shaped(p_176727_, 3).group("sign").define('#', p_176728_).define('X', Items.STICK).pattern("###").pattern("###").pattern(" X ");
    }

    public static void coloredWoolFromWhiteWoolAndDye(Consumer<FinishedRecipe> p_126062_, ItemLike p_126063_, ItemLike p_126064_) {
        ShapelessRecipeBuilder.shapeless(p_126063_).requires(p_126064_).requires(Blocks.WHITE_WOOL).group("wool").unlockedBy("has_white_wool", has(Blocks.WHITE_WOOL)).save(p_126062_);
    }

    public static void carpet(Consumer<FinishedRecipe> p_176717_, ItemLike p_176718_, ItemLike p_176719_) {
        ShapedRecipeBuilder.shaped(p_176718_, 3).define('#', p_176719_).pattern("##").group("carpet").unlockedBy(getHasName(p_176719_), has(p_176719_)).save(p_176717_);
    }

    public static void coloredCarpetFromWhiteCarpetAndDye(Consumer<FinishedRecipe> p_126070_, ItemLike p_126071_, ItemLike p_126072_) {
        ShapedRecipeBuilder.shaped(p_126071_, 8).define('#', Blocks.WHITE_CARPET).define('$', p_126072_).pattern("###").pattern("#$#").pattern("###").group("carpet").unlockedBy("has_white_carpet", has(Blocks.WHITE_CARPET)).unlockedBy(getHasName(p_126072_), has(p_126072_)).save(p_126070_, getConversionRecipeName(p_126071_, Blocks.WHITE_CARPET));
    }

    public static void bedFromPlanksAndWool(Consumer<FinishedRecipe> p_126074_, ItemLike p_126075_, ItemLike p_126076_) {
        ShapedRecipeBuilder.shaped(p_126075_).define('#', p_126076_).define('X', ItemTags.PLANKS).pattern("###").pattern("XXX").group("bed").unlockedBy(getHasName(p_126076_), has(p_126076_)).save(p_126074_);
    }

    public static void bedFromWhiteBedAndDye(Consumer<FinishedRecipe> p_126078_, ItemLike p_126079_, ItemLike p_126080_) {
        ShapelessRecipeBuilder.shapeless(p_126079_).requires(Items.WHITE_BED).requires(p_126080_).group("dyed_bed").unlockedBy("has_bed", has(Items.WHITE_BED)).save(p_126078_, getConversionRecipeName(p_126079_, Items.WHITE_BED));
    }

    public static void banner(Consumer<FinishedRecipe> p_126082_, ItemLike p_126083_, ItemLike p_126084_) {
        ShapedRecipeBuilder.shaped(p_126083_).define('#', p_126084_).define('|', Items.STICK).pattern("###").pattern("###").pattern(" | ").group("banner").unlockedBy(getHasName(p_126084_), has(p_126084_)).save(p_126082_);
    }

    public static void stainedGlassFromGlassAndDye(Consumer<FinishedRecipe> p_126086_, ItemLike p_126087_, ItemLike p_126088_) {
        ShapedRecipeBuilder.shaped(p_126087_, 8).define('#', Blocks.GLASS).define('X', p_126088_).pattern("###").pattern("#X#").pattern("###").group("stained_glass").unlockedBy("has_glass", has(Blocks.GLASS)).save(p_126086_);
    }

    public static void stainedGlassPaneFromStainedGlass(Consumer<FinishedRecipe> p_126090_, ItemLike p_126091_, ItemLike p_126092_) {
        ShapedRecipeBuilder.shaped(p_126091_, 16).define('#', p_126092_).pattern("###").pattern("###").group("stained_glass_pane").unlockedBy("has_glass", has(p_126092_)).save(p_126090_);
    }

    public static void stainedGlassPaneFromGlassPaneAndDye(Consumer<FinishedRecipe> p_126094_, ItemLike p_126095_, ItemLike p_126096_) {
        ShapedRecipeBuilder.shaped(p_126095_, 8).define('#', Blocks.GLASS_PANE).define('$', p_126096_).pattern("###").pattern("#$#").pattern("###").group("stained_glass_pane").unlockedBy("has_glass_pane", has(Blocks.GLASS_PANE)).unlockedBy(getHasName(p_126096_), has(p_126096_)).save(p_126094_, getConversionRecipeName(p_126095_, Blocks.GLASS_PANE));
    }

    public static void coloredTerracottaFromTerracottaAndDye(Consumer<FinishedRecipe> p_126098_, ItemLike p_126099_, ItemLike p_126100_) {
        ShapedRecipeBuilder.shaped(p_126099_, 8).define('#', Blocks.TERRACOTTA).define('X', p_126100_).pattern("###").pattern("#X#").pattern("###").group("stained_terracotta").unlockedBy("has_terracotta", has(Blocks.TERRACOTTA)).save(p_126098_);
    }

    public static void concretePowder(Consumer<FinishedRecipe> p_126102_, ItemLike p_126103_, ItemLike p_126104_) {
        ShapelessRecipeBuilder.shapeless(p_126103_, 8).requires(p_126104_).requires(Blocks.SAND, 4).requires(Blocks.GRAVEL, 4).group("concrete_powder").unlockedBy("has_sand", has(Blocks.SAND)).unlockedBy("has_gravel", has(Blocks.GRAVEL)).save(p_126102_);
    }

    public static void candle(Consumer<FinishedRecipe> p_176543_, ItemLike p_176544_, ItemLike p_176545_) {
        ShapelessRecipeBuilder.shapeless(p_176544_).requires(Blocks.CANDLE).requires(p_176545_).group("dyed_candle").unlockedBy(getHasName(p_176545_), has(p_176545_)).save(p_176543_);
    }

    public static void wall(Consumer<FinishedRecipe> p_176613_, ItemLike p_176614_, ItemLike p_176615_) {
        wallBuilder(p_176614_, Ingredient.of(p_176615_)).unlockedBy(getHasName(p_176615_), has(p_176615_)).save(p_176613_);
    }

    public static RecipeBuilder wallBuilder(ItemLike p_176515_, Ingredient p_176516_) {
        return ShapedRecipeBuilder.shaped(p_176515_, 6).define('#', p_176516_).pattern("###").pattern("###");
    }

    public static void polished(Consumer<FinishedRecipe> p_176641_, ItemLike p_176642_, ItemLike p_176643_) {
        polishedBuilder(p_176642_, Ingredient.of(p_176643_)).unlockedBy(getHasName(p_176643_), has(p_176643_)).save(p_176641_);
    }

    public static RecipeBuilder polishedBuilder(ItemLike p_176605_, Ingredient p_176606_) {
        return ShapedRecipeBuilder.shaped(p_176605_, 4).define('S', p_176606_).pattern("SS").pattern("SS");
    }

    public static void cut(Consumer<FinishedRecipe> p_176653_, ItemLike p_176654_, ItemLike p_176655_) {
        cutBuilder(p_176654_, Ingredient.of(p_176655_)).unlockedBy(getHasName(p_176655_), has(p_176655_)).save(p_176653_);
    }

    public static ShapedRecipeBuilder cutBuilder(ItemLike p_176635_, Ingredient p_176636_) {
        return ShapedRecipeBuilder.shaped(p_176635_, 4).define('#', p_176636_).pattern("##").pattern("##");
    }

    public static void chiseled(Consumer<FinishedRecipe> p_176665_, ItemLike p_176666_, ItemLike p_176667_) {
        chiseledBuilder(p_176666_, Ingredient.of(p_176667_)).unlockedBy(getHasName(p_176667_), has(p_176667_)).save(p_176665_);
    }

    public static ShapedRecipeBuilder chiseledBuilder(ItemLike p_176647_, Ingredient p_176648_) {
        return ShapedRecipeBuilder.shaped(p_176647_).define('#', p_176648_).pattern("#").pattern("#");
    }

    public static void stonecutterResultFromBase(Consumer<FinishedRecipe> p_176736_, ItemLike p_176737_, ItemLike p_176738_) {
        stonecutterResultFromBase(p_176736_, p_176737_, p_176738_, 1);
    }

    public static void stonecutterResultFromBase(Consumer<FinishedRecipe> p_176547_, ItemLike p_176548_, ItemLike p_176549_, int p_176550_) {
        SingleItemRecipeBuilder.stonecutting(Ingredient.of(p_176549_), p_176548_, p_176550_).unlockedBy(getHasName(p_176549_), has(p_176549_)).save(p_176547_, getConversionRecipeName(p_176548_, p_176549_) + "_stonecutting");
    }

    public static void smeltingResultFromBase(Consumer<FinishedRecipe> p_176740_, ItemLike p_176741_, ItemLike p_176742_) {
        SimpleCookingRecipeBuilder.smelting(Ingredient.of(p_176742_), p_176741_, 0.1F, 200).unlockedBy(getHasName(p_176742_), has(p_176742_)).save(p_176740_);
    }

    public static void nineBlockStorageRecipes(Consumer<FinishedRecipe> p_176744_, ItemLike p_176745_, ItemLike p_176746_) {
        nineBlockStorageRecipes(p_176744_, p_176745_, p_176746_, getSimpleRecipeName(p_176746_), null, getSimpleRecipeName(p_176745_), null);
    }

    public static void nineBlockStorageRecipesWithCustomPacking(Consumer<FinishedRecipe> p_176563_, ItemLike p_176564_, ItemLike p_176565_, String p_176566_, String p_176567_) {
        nineBlockStorageRecipes(p_176563_, p_176564_, p_176565_, p_176566_, p_176567_, getSimpleRecipeName(p_176564_), null);
    }

    public static void nineBlockStorageRecipesRecipesWithCustomUnpacking(Consumer<FinishedRecipe> p_176617_, ItemLike p_176618_, ItemLike p_176619_, String p_176620_, String p_176621_) {
        nineBlockStorageRecipes(p_176617_, p_176618_, p_176619_, getSimpleRecipeName(p_176619_), null, p_176620_, p_176621_);
    }

    public static void nineBlockStorageRecipes(Consumer<FinishedRecipe> p_176569_, ItemLike p_176570_, ItemLike p_176571_, String p_176572_, @Nullable String p_176573_, String p_176574_, @Nullable String p_176575_) {
        ShapelessRecipeBuilder.shapeless(p_176570_, 9).requires(p_176571_).group(p_176575_).unlockedBy(getHasName(p_176571_), has(p_176571_)).save(p_176569_, new ResourceLocation(p_176574_));
        ShapedRecipeBuilder.shaped(p_176571_).define('#', p_176570_).pattern("###").pattern("###").pattern("###").group(p_176573_).unlockedBy(getHasName(p_176570_), has(p_176570_)).save(p_176569_, new ResourceLocation(p_176572_));
    }


    public static void simpleCookingRecipe(Consumer<FinishedRecipe> p_176584_, String p_176585_, SimpleCookingSerializer<?> p_176586_, int p_176587_, ItemLike p_176588_, ItemLike p_176589_, float p_176590_) {
        SimpleCookingRecipeBuilder.cooking(Ingredient.of(p_176588_), p_176589_, p_176590_, p_176587_, p_176586_).unlockedBy(getHasName(p_176588_), has(p_176588_)).save(p_176584_, getItemName(p_176589_) + "_from_" + p_176585_);
    }



    public static Block getBaseBlock(BlockFamily p_176524_, BlockFamily.Variant p_176525_) {
        if (p_176525_ == BlockFamily.Variant.CHISELED) {
            if (!p_176524_.getVariants().containsKey(BlockFamily.Variant.SLAB)) {
                throw new IllegalStateException("Slab is not defined for the family.");
            } else {
                return p_176524_.get(BlockFamily.Variant.SLAB);
            }
        } else {
            return p_176524_.getBaseBlock();
        }
    }

    public static EnterBlockTrigger.TriggerInstance insideOf(Block p_125980_) {
        return new EnterBlockTrigger.TriggerInstance(EntityPredicate.Composite.ANY, p_125980_, StatePropertiesPredicate.ANY);
    }
}
